Scripts {pliman} 67ª RBRAS e 20º SEAGRO
1 Pacotes
2 Importação e manipulação
3 Segmentação
## [1] "R" "G" "B" "NR" "NG" "NB" "GB" "RB" "GR"
## [10] "BI" "BIM" "SCI" "GLI" "HI" "NGRDI" "NDGBI" "NDRBI" "I"
## [19] "S" "VARI" "HUE" "HUE2" "BGI" "L" "GRAY" "GLAI" "CI"
## [28] "SHP" "RI" "G-B" "G-R" "R-G" "R-B" "B-R" "B-G" "DGCI"
## [37] "GRAY2" "L*" "a" "b*" "L*-a" "L*-b" "b*-a"
# Threshold adaptativo
adaptive <- image_import("adaptive.jpg")
# Ìndice de imagem
ind <- image_index(adaptive, index = "R")# Segmentação utilizando threshold adaptativo
image_segment(adaptive,
index = "R",
# filter = 5,
# fill_hull = TRUE,
threshold = "adaptive")4 Análise de objetos
4.1 Imagem única
grains <- image_import("grains.jpg", plot = TRUE)
# Analisar os objetos
res <- analyze_objects(grains, index = "GRAY")# Algumas funcionalidades
res <-
analyze_objects(grains,
index = "GRAY",
lower_noise = 0.4, # remove ruídos maiores
show_contour = FALSE,
marker = "point")res <-
analyze_objects(grains,
index = "GRAY",
topn_upper = 10, # Somente os 10 maiores grãos
show_contour = FALSE,
marker = "point")4.2 Processamento em lote com correção (referência)
4.2.1 Pelo tamanho da referência
# Analisar os objetos
res <-
analyze_objects(pattern = "P",
dir_original = "flax_grain", # subpasta com as imagens originais
dir_processed = "proc", # subpasta com as imagens processadas
reference = TRUE, # indica que há uma referência
reference_larger = TRUE, # indica que a referência é o maior objeto
reference_area = 6, # a referência tem 6 cm2
index = "GRAY",
show_contour = FALSE,
marker = "point",
plot = FALSE,
save_image = TRUE)## Processing image P01 |======= | 17% 00:00:00
## Processing image P02 |============== | 33% 00:00:03
## Processing image P03 |====================== | 50% 00:00:06
## Processing image P04 |============================= | 67% 00:00:10
## Processing image P05 |==================================== | 83% 00:00:13
## Processing image P06 |===========================================| 100% 00:00:16
## --------------------------------------------
## Image Objects
## P01 277
## P02 91
## P03 179
## P04 112
## P05 22
## P06 78
## --------------------------------------------
4.2.2 Pela cor da referência
flax <- image_import("flax_af/A2_32_3.jpg", plot = TRUE)
# Índice para segmentar a referência e folhas do fundo
image_segment_iter(flax,
index = c("R/(G/B)", "B-R"),
ncol = 3)## image pixels percent
## 1 original 806490 100.00000
## 2 seg1 129657 16.07670
## 3 seg2 38517 29.70684
# Note que agora o processamento é realizado de forma paralela
res <-
analyze_objects(pattern = "A",
dir_original = "flax_af",
reference = TRUE,
reference_area = 20,
back_fore_index = "R/(G/B)",
fore_ref_index = "B-R",
watershed = FALSE,
filter = 2,
plot = FALSE,
parallel = TRUE)## Error in unserialize(socklist[[n]]): erro ao ler a partir de conexão
## Error in serialize(data, node$con): erro ao escrever na conexão
merged <- get_measures(res)
# Organizar os dados para ajuste do modelo Logístico
df_plot <-
merged$summary |>
separate_col(img,
into = c("avaliacao", "das", "bloco")) |>
mutate(das = as.numeric(das))## Error in names(df) <- into: atributo 'names' [3] deve ter o mesmo comprimento que o vetor [1]
formula <- y ~ b1/(1 + exp(b2 - b3 * x))
ggplot(df_plot, aes(das, area_sum)) +
geom_smooth(method = "nls",
method.args = list(formula = formula,
start = c(b1 = 248,
b2 = 6,
b3 = 0.07)),
se = FALSE,
color = "red") +
stat_summary(fun.data = mean_se,
geom = "errorbar",
width = 0.5) +
stat_summary(fun = mean,
geom = "point",
col = "blue",
size = 3) +
scale_x_continuous(breaks = unique(df_plot$das)) +
scale_y_continuous(breaks = seq(0, 150, by = 25)) +
labs(x = "Dias após a semeadura",
y = expression(Área~foliar~média~(cm^2~planta^{-1}))) +
theme_bw(base_size = 16) +
theme(panel.grid = element_blank()) ## Error in eval(expr, envir, enclos): objeto 'df_plot' não encontrado
5 Ortomosaicos
Imagens disponibilizadas por Filipe Matias, no github do FIELDimageR
5.1 Cobertura vegetal (canopy)
# preparar a imagem
# Somente iterativo
# prep <- image_prepare_mv(img)
prep <-
img |>
image_rotate(-2.076, plot = FALSE) |>
image_crop(width = 194:1075,
height = 143:379,
plot = TRUE)res <-
analyze_objects_shp(prep,
nrow = 16,
ncol = 9,
index = "HUE",
object_index = c("NGRDI", "DGCI"))
# cobertura de solo
plot_index_shp(res)5.2 Índices de vegetação
5.3 Stand de plantas
res <-
analyze_objects_shp(stand,
index = "NGRDI",
invert = TRUE,
nrow = 7,
ncol = 1)
par(mfrow = c(1, 2))
# cobertura de solo
plot_index_shp(res)
# mapeamento das plantas (distâncias e CV(%))
object_mark(res)
mapped <- object_map(res)
# coeficiente de variação dentro da linha
barplot(mapped$cvs)6 Fitopatometria
6.1 Iterativa
6.2 Usando paletas
sev <-
measure_disease(folha,
img_healthy = pals$soja_h.png, # paleta para folha sadia
img_symptoms = pals$soja_s.png, # paleta para folha doente
img_background = pals$soja_b.png) # paleta para fundo6.3 Usando índices de imagem
# Índice para segmentar a folha do fundo, depois a doença da folha
image_segment_iter(folha,
index = c("B", "NGRDI"),
ncol = 3)## image pixels percent
## 1 original 4813707 100.00000
## 2 seg1 2781900 57.79122
## 3 seg2 384237 13.81203
# IMPORTANTE: theshold vai alterar a severidade
sev2 <-
measure_disease(folha,
index_lb = "B", # índice para segmentar a folha do fundo
index_dh = "NGRDI", # índice para segmentar folha doente e sadia
threshold = c("Otsu", 0)) # threshold para os dois índices, respectivamente# em lote (utilizando as paletas)
sev3 <-
measure_disease(pattern = "soy_",
dir_original = "soybean_rust", # pasta com as imagens originais
dir_processed = "proc_rust", # pasta com as imagens processadas
save_image = TRUE,
plot = FALSE,
img_healthy = pals$soja_h.png,
img_symptoms = pals$soja_s.png,
img_background = pals$soja_b.png,
parallel = TRUE)
# standard area diagrams
sad(sev3, n = 6)sev4 <-
measure_disease(pattern = "soy_",
dir_original = "soybean_rust",
plot = FALSE,
index_lb = "B",
index_dh = "NGRDI",
threshold = c("Otsu", 0),
parallel = TRUE)
# paletas vs índices de imagem
df <-
data.frame(paletas = sev3$severity$symptomatic,
índices = sev4$severity$symptomatic)
dfggplot(df, aes(paletas, índices)) +
geom_point() +
geom_abline(intercept = 0, slope = 1, color = "red") +
theme_bw(base_size = 16) +
xlim(0, 100) +
ylim(0, 100) +
coord_equal()Universidade Federal de Santa Catarina, https://olivoto.netlify.app/↩︎
LS0tDQp0aXRsZTogIlNjcmlwdHMge3BsaW1hbn0gNjfCqiBSQlJBUyBlIDIwwrogU0VBR1JPIg0KYXV0aG9yOg0KICAtIFRpYWdvIE9saXZvdG9eW1VuaXZlcnNpZGFkZSBGZWRlcmFsIGRlIFNhbnRhIENhdGFyaW5hLCBodHRwczovL29saXZvdG8ubmV0bGlmeS5hcHAvXQ0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQoNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KDQpgYGANCg0KWyFbXShsb2dvLnBuZyldKGh0dHBzOi8vNjdyYnJhczIwc2VhZ3JvLmNvbS5ici8pDQoNCiMgUGFjb3Rlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGxpbWFuKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpzZXR3ZCgiRDovRGVza3RvcC9VRlNDL2N1cnNvcy9wbGltYW42N3JicmFzIikNCnNldF93ZF9oZXJlKCkNCiMgc2V0X3BsaW1hbl92aWV3ZXIoIm1hcHZpZXciKQ0KDQpgYGANCg0KIyBJbXBvcnRhw6fDo28gZSBtYW5pcHVsYcOnw6NvDQojIyBJbXBvcnRhw6fDo28NCmBgYHtyfQ0KbGVhdmVzIDwtIGltYWdlX2ltcG9ydCgibGVhdmVzLmpwZyIsIHBsb3QgPSBUUlVFKQ0KDQpgYGANCg0KIyMgUmVzb2x1w6fDo28NCmBgYHtyIGV2YWw9RkFMU0V9DQpkcGkobGVhdmVzLCB2aWV3ZXIgPSAibWFwdmlldyIpDQpgYGANCg0KDQojIyBDb3J0YXIsIGdpcmFyIGUgcmVkaW1lbnNpb25hcg0KYGBge3J9DQpjcm9wIDwtIGltYWdlX2F1dG9jcm9wKGxlYXZlcywgcGxvdCA9IFRSVUUpDQojIGNyb3AgPC0gaW1hZ2VfY3JvcChsZWF2ZXMsIHZpZXdlciA9ICJtYXB2aWV3IikNCg0KY3JvcCA8LSBpbWFnZV9jcm9wKGxlYXZlcywNCiAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDEzNzo5MTIsIA0KICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IDU5OjczOSkNCmBgYA0KDQoNCiMgU2VnbWVudGHDp8Ojbw0KYGBge3J9DQojIMONbmRpY2VzIHBhcmEgc2VnbWVudGHDp8Ojbw0KcGxpbWFuX2luZGV4ZXMoKQ0KaW5kZXggPC0gaW1hZ2VfaW5kZXgobGVhdmVzLCBpbmRleCA9IGMoIlIiLCAiRyIsICJCIiwgIkItUiIpKQ0KcGxvdChpbmRleCwgdHlwZSA9ICJkZW5zaXR5IikNCg0KIyBJbWFnZW0gYmluw6FyaWENCmJpbmFyeSA8LSBpbWFnZV9iaW5hcnkobGVhdmVzLCBpbmRleCA9ICJCLVIiKQ0KYmluYXJ5IDwtIA0KICBpbWFnZV9iaW5hcnkobGVhdmVzLA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGludmVydCA9IFRSVUUpDQpiaW5hcnkgPC0gDQogIGltYWdlX2JpbmFyeShsZWF2ZXMsIA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGZpbGxfaHVsbCA9IFRSVUUpDQpiaW5hcnkgPC0gDQogIGltYWdlX2JpbmFyeShsZWF2ZXMsIA0KICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIiwNCiAgICAgICAgICAgICAgIGZpbHRlciA9IDUsDQogICAgICAgICAgICAgICBmaWxsX2h1bGwgPSBUUlVFKQ0KDQojIFNlZ21lbnRhw6fDo28NCnNlZyA8LSBpbWFnZV9zZWdtZW50KGxlYXZlcywNCiAgICAgICAgICAgICAgICAgICAgICMgdGhyZXNob2xkID0gMC4xLA0KICAgICAgICAgICAgICAgICAgICAgIyB0aHJlc2hvbGQgPSAiYWEiLA0KICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSAiQi1SIikNCg0KIyBUaHJlc2hvbGQgYWRhcHRhdGl2bw0KYWRhcHRpdmUgPC0gaW1hZ2VfaW1wb3J0KCJhZGFwdGl2ZS5qcGciKQ0KIyDDjG5kaWNlIGRlIGltYWdlbQ0KaW5kIDwtIGltYWdlX2luZGV4KGFkYXB0aXZlLCBpbmRleCA9ICJSIikNCnBsb3QoaW5kLCB0eXBlID0gImRlbnNpdHkiKQ0KDQojIFNlZ21lbnRhw6fDo28gcG9yIE90c3UNCmltYWdlX3NlZ21lbnQoYWRhcHRpdmUsIGluZGV4ID0gIlIiKQ0KDQojIFNlZ21lbnRhw6fDo28gdXRpbGl6YW5kbyB0aHJlc2hvbGQgYWRhcHRhdGl2bw0KaW1hZ2Vfc2VnbWVudChhZGFwdGl2ZSwNCiAgICAgICAgICAgICAgaW5kZXggPSAiUiIsDQogICAgICAgICAgICAgICMgZmlsdGVyID0gNSwNCiAgICAgICAgICAgICAgIyBmaWxsX2h1bGwgPSBUUlVFLA0KICAgICAgICAgICAgICB0aHJlc2hvbGQgPSAiYWRhcHRpdmUiKQ0KYGBgDQoNCg0KDQojIEFuw6FsaXNlIGRlIG9iamV0b3MNCiMjIEltYWdlbSDDum5pY2ENCmBgYHtyfQ0KZ3JhaW5zIDwtIGltYWdlX2ltcG9ydCgiZ3JhaW5zLmpwZyIsIHBsb3QgPSBUUlVFKQ0KDQojIEFuYWxpc2FyIG9zIG9iamV0b3MNCnJlcyA8LSBhbmFseXplX29iamVjdHMoZ3JhaW5zLCBpbmRleCA9ICJHUkFZIikNCnJlcyRzdGF0aXN0aWNzDQoNCiMgQWxndW1hcyBmdW5jaW9uYWxpZGFkZXMNCnJlcyA8LSANCiAgYW5hbHl6ZV9vYmplY3RzKGdyYWlucywgDQogICAgICAgICAgICAgICAgICBpbmRleCA9ICJHUkFZIiwNCiAgICAgICAgICAgICAgICAgIGxvd2VyX25vaXNlID0gMC40LCAgICAgICMgcmVtb3ZlIHJ1w61kb3MgbWFpb3Jlcw0KICAgICAgICAgICAgICAgICAgc2hvd19jb250b3VyID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSAicG9pbnQiKQ0KcGxvdChyZXMpDQoNCnJlcyA8LSANCiAgYW5hbHl6ZV9vYmplY3RzKGdyYWlucywgDQogICAgICAgICAgICAgICAgICBpbmRleCA9ICJHUkFZIiwNCiAgICAgICAgICAgICAgICAgIHRvcG5fdXBwZXIgPSAxMCwgICAgICAgICMgU29tZW50ZSBvcyAxMCBtYWlvcmVzIGdyw6Nvcw0KICAgICAgICAgICAgICAgICAgc2hvd19jb250b3VyID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSAicG9pbnQiKQ0KDQpgYGANCg0KDQojIyBQcm9jZXNzYW1lbnRvIGVtIGxvdGUgY29tIGNvcnJlw6fDo28gKHJlZmVyw6puY2lhKQ0KIyMjIFBlbG8gdGFtYW5obyBkYSByZWZlcsOqbmNpYQ0KYGBge3J9DQojIEFuYWxpc2FyIG9zIG9iamV0b3MNCnJlcyA8LSANCiAgYW5hbHl6ZV9vYmplY3RzKHBhdHRlcm4gPSAiUCIsDQogICAgICAgICAgICAgICAgICBkaXJfb3JpZ2luYWwgPSAiZmxheF9ncmFpbiIsICAgICMgc3VicGFzdGEgY29tIGFzIGltYWdlbnMgb3JpZ2luYWlzDQogICAgICAgICAgICAgICAgICBkaXJfcHJvY2Vzc2VkID0gInByb2MiLCAgICAgICAgICMgc3VicGFzdGEgY29tIGFzIGltYWdlbnMgcHJvY2Vzc2FkYXMNCiAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZSA9IFRSVUUsICAgICAgICAgICAgICAgIyBpbmRpY2EgcXVlIGjDoSB1bWEgcmVmZXLDqm5jaWENCiAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZV9sYXJnZXIgPSBUUlVFLCAgICAgICAgIyBpbmRpY2EgcXVlIGEgcmVmZXLDqm5jaWEgw6kgbyBtYWlvciBvYmpldG8gDQogICAgICAgICAgICAgICAgICByZWZlcmVuY2VfYXJlYSA9IDYsICAgICAgICAgICAgICMgYSByZWZlcsOqbmNpYSB0ZW0gNiBjbTINCiAgICAgICAgICAgICAgICAgIGluZGV4ID0gIkdSQVkiLA0KICAgICAgICAgICAgICAgICAgc2hvd19jb250b3VyID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSAicG9pbnQiLA0KICAgICAgICAgICAgICAgICAgcGxvdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgc2F2ZV9pbWFnZSA9IFRSVUUpDQoNCmhpc3QocmVzJHJlc3VsdHMkbGVuZ3RoKQ0KDQpgYGANCg0KDQojIyMgUGVsYSBjb3IgZGEgcmVmZXLDqm5jaWENCmBgYHtyfQ0KI3wgb3V0LXdpZHRoOiAiMTAwJSINCmZsYXggPC0gaW1hZ2VfaW1wb3J0KCJmbGF4X2FmL0EyXzMyXzMuanBnIiwgcGxvdCA9IFRSVUUpDQoNCiMgw41uZGljZSBwYXJhIHNlZ21lbnRhciBhIHJlZmVyw6puY2lhIGUgZm9saGFzIGRvIGZ1bmRvDQppbWFnZV9zZWdtZW50X2l0ZXIoZmxheCwgDQogICAgICAgICAgICAgICAgICAgaW5kZXggPSBjKCJSLyhHL0IpIiwgIkItUiIpLA0KICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQ0KDQoNCiMgTm90ZSBxdWUgYWdvcmEgbyBwcm9jZXNzYW1lbnRvIMOpIHJlYWxpemFkbyBkZSBmb3JtYSBwYXJhbGVsYQ0KcmVzIDwtDQogIGFuYWx5emVfb2JqZWN0cyhwYXR0ZXJuID0gIkEiLA0KICAgICAgICAgICAgICAgICAgZGlyX29yaWdpbmFsID0gImZsYXhfYWYiLA0KICAgICAgICAgICAgICAgICAgcmVmZXJlbmNlID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZV9hcmVhID0gMjAsDQogICAgICAgICAgICAgICAgICBiYWNrX2ZvcmVfaW5kZXggPSAiUi8oRy9CKSIsDQogICAgICAgICAgICAgICAgICBmb3JlX3JlZl9pbmRleCA9ICJCLVIiLA0KICAgICAgICAgICAgICAgICAgd2F0ZXJzaGVkID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBmaWx0ZXIgPSAyLA0KICAgICAgICAgICAgICAgICAgcGxvdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgcGFyYWxsZWwgPSBUUlVFKQ0KDQptZXJnZWQgPC0gZ2V0X21lYXN1cmVzKHJlcykNCg0KDQojIE9yZ2FuaXphciBvcyBkYWRvcyBwYXJhIGFqdXN0ZSBkbyBtb2RlbG8gTG9nw61zdGljbw0KZGZfcGxvdCA8LSANCiAgbWVyZ2VkJHN1bW1hcnkgfD4gDQogIHNlcGFyYXRlX2NvbChpbWcsIA0KICAgICAgICAgICAgICAgaW50byA9IGMoImF2YWxpYWNhbyIsICJkYXMiLCAiYmxvY28iKSkgfD4gDQogIG11dGF0ZShkYXMgPSBhcy5udW1lcmljKGRhcykpDQoNCmZvcm11bGEgPC0geSB+IGIxLygxICsgZXhwKGIyIC0gYjMgKiB4KSkNCg0KZ2dwbG90KGRmX3Bsb3QsIGFlcyhkYXMsIGFyZWFfc3VtKSkgKyANCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gIm5scyIsDQogICAgICAgICAgICAgIG1ldGhvZC5hcmdzID0gbGlzdChmb3JtdWxhID0gZm9ybXVsYSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gYyhiMSA9IDI0OCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiMiA9IDYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYjMgPSAwLjA3KSksDQogICAgICAgICAgICAgIHNlID0gRkFMU0UsDQogICAgICAgICAgICAgIGNvbG9yID0gInJlZCIpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwNCiAgICAgICAgICAgICAgIGdlb20gPSAiZXJyb3JiYXIiLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sDQogICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwNCiAgICAgICAgICAgICAgIGNvbCA9ICJibHVlIiwNCiAgICAgICAgICAgICAgIHNpemUgPSAzKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSB1bmlxdWUoZGZfcGxvdCRkYXMpKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTUwLCBieSA9IDI1KSkgKw0KICBsYWJzKHggPSAiRGlhcyBhcMOzcyBhIHNlbWVhZHVyYSIsDQogICAgICAgeSA9IGV4cHJlc3Npb24ow4FyZWF+Zm9saWFyfm3DqWRpYX4oY21eMn5wbGFudGFeey0xfSkpKSArDQogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArDQogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpIA0KDQpgYGANCg0KDQoNCiMgT3J0b21vc2FpY29zDQpJbWFnZW5zIGRpc3BvbmliaWxpemFkYXMgcG9yIEZpbGlwZSBNYXRpYXMsIG5vIGdpdGh1YiBkbyBbRklFTERpbWFnZVJdKFJodHRwczovL2dpdGh1Yi5jb20vT3BlbkRyb25lTWFwL0ZJRUxEaW1hZ2VSKQ0KDQojIyBDb2JlcnR1cmEgdmVnZXRhbCAoY2Fub3B5KQ0KDQpgYGB7cn0NCiMgaW1hZ2VtDQppbWcgPC0gDQogIGltYWdlX2ltcG9ydCgicG90YXRvZXMudGlmIiwgcGF0aCA9ICJvcnRob21vc2FpYyIpIHw+IA0KICBpbWFnZV9ob3Jpem9udGFsKCkNCg0KcGxvdChpbWcpDQoNCiMgcHJlcGFyYXIgYSBpbWFnZW0NCiMgU29tZW50ZSBpdGVyYXRpdm8NCiMgcHJlcCA8LSBpbWFnZV9wcmVwYXJlX212KGltZykNCnByZXAgPC0gDQogIGltZyB8PiANCiAgaW1hZ2Vfcm90YXRlKC0yLjA3NiwgcGxvdCA9IEZBTFNFKSB8PiANCiAgaW1hZ2VfY3JvcCh3aWR0aCA9IDE5NDoxMDc1LA0KICAgICAgICAgICAgIGhlaWdodCA9IDE0MzozNzksDQogICAgICAgICAgICAgcGxvdCA9IFRSVUUpDQoNCg0KIyDDrW5kaWNlIHBhcmEgc2VnbWVudGHDp8Ojbw0KaW1hZ2VfaW5kZXgocHJlcCwgaW5kZXggPSAgIkhVRSIpDQoNCg0KcmVzIDwtIA0KICBhbmFseXplX29iamVjdHNfc2hwKHByZXAsDQogICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDE2LA0KICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA5LA0KICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gIkhVRSIsDQogICAgICAgICAgICAgICAgICAgICAgb2JqZWN0X2luZGV4ID0gYygiTkdSREkiLCAiREdDSSIpKQ0KDQojIGNvYmVydHVyYSBkZSBzb2xvDQpwbG90X2luZGV4X3NocChyZXMpDQoNCiMgcmVzdW1pciBhcyBpbmZvcm1hw6fDtWVzDQpyZXN1bHRzIDwtIGdldF9tZWFzdXJlcyhyZXMpDQpgYGANCg0KDQoNCiMjIMONbmRpY2VzIGRlIHZlZ2V0YcOnw6NvDQoNCmBgYHtyfQ0KIyBOw612ZWwgZGUgcGFyY2VsYQ0KcGxvdF9pbmRleF9zaHAocmVzLCBhdHRyaWJ1dGUgPSAiTkdSREkiKQ0KDQojIE7DrXZlbCBkZSBwaXhlbA0KcGxvdF9pbmRleChvYmplY3QgPSByZXMsIGluZGV4ID0gIkRHQ0kiKQ0KIyBwbG90X2luZGV4KG9iamVjdCA9IHJlcywgaW5kZXggPSAiREdDSSIsIHZpZXdlciA9ICJtYXAiKQ0KDQojIHJlc3VtaXIgYXMgaW5mb3JtYcOnw7Vlcw0KcmVzdWx0cyA8LSBnZXRfbWVhc3VyZXMocmVzKQ0KYGBgDQoNCg0KIyMgU3RhbmQgZGUgcGxhbnRhcw0KDQpgYGB7cn0NCiMgaW1hZ2VtDQpzdGFuZCA8LSBpbWFnZV9pbXBvcnQoInN0YW5kLmpwZyIsIHBhdGggPSAib3J0aG9tb3NhaWMiLCBwbG90ID0gVFJVRSkNCg0KDQojIMOtbmRpY2UgcGFyYSBzZWdtZW50YcOnw6NvDQppbWFnZV9zZWdtZW50KHN0YW5kLCAiSFVFIikNCmltYWdlX3NlZ21lbnQoc3RhbmQsICJOR1JESSIpDQppbWFnZV9zZWdtZW50KHN0YW5kLCAiTkdSREkiLCBpbnZlcnQgPSBUUlVFKQ0KDQpyZXMgPC0gDQogIGFuYWx5emVfb2JqZWN0c19zaHAoc3RhbmQsDQogICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSAiTkdSREkiLA0KICAgICAgICAgICAgICAgICAgICAgIGludmVydCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDcsDQogICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEpDQoNCnBhcihtZnJvdyA9IGMoMSwgMikpDQojIGNvYmVydHVyYSBkZSBzb2xvDQpwbG90X2luZGV4X3NocChyZXMpDQoNCiMgbWFwZWFtZW50byBkYXMgcGxhbnRhcyAoZGlzdMOibmNpYXMgZSBDViglKSkNCm9iamVjdF9tYXJrKHJlcykNCm1hcHBlZCA8LSAgb2JqZWN0X21hcChyZXMpDQoNCiMgY29lZmljaWVudGUgZGUgdmFyaWHDp8OjbyBkZW50cm8gZGEgbGluaGENCmJhcnBsb3QobWFwcGVkJGN2cykNCg0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KDQoNCg0KIyBGaXRvcGF0b21ldHJpYQ0KIyMgSXRlcmF0aXZhDQpgYGB7cn0NCmZvbGhhIDwtIGltYWdlX3BsaW1hbigic2V2X2xlYWYuanBnIiwgcGxvdCA9IFRSVUUpDQojIG1lYXN1cmVfZGlzZWFzZV9pdGVyKGZvbGhhLCB2aWV3ZXIgPSAibWFwdmlldyIpDQoNCmBgYA0KDQoNCiMjIFVzYW5kbyBwYWxldGFzDQpgYGB7cn0NCmZvbGhhIDwtIGltYWdlX2ltcG9ydCgic295YmVhbl9ydXN0L3NveV8xLmpwZyIsIHBsb3QgPSBUUlVFKQ0KcGFscyA8LSBpbWFnZV9pbXBvcnQocGF0dGVybiA9ICJzb2phXyIsDQogICAgICAgICAgICAgICAgICAgICBwYXRoID0gInNveWJlYW5fcnVzdCIsDQogICAgICAgICAgICAgICAgICAgICBwbG90ID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQ0Kc2V2IDwtIA0KICBtZWFzdXJlX2Rpc2Vhc2UoZm9saGEsDQogICAgICAgICAgICAgICAgICBpbWdfaGVhbHRoeSA9IHBhbHMkc29qYV9oLnBuZywgICAgICMgcGFsZXRhIHBhcmEgZm9saGEgc2FkaWENCiAgICAgICAgICAgICAgICAgIGltZ19zeW1wdG9tcyA9IHBhbHMkc29qYV9zLnBuZywgICAgIyBwYWxldGEgcGFyYSBmb2xoYSBkb2VudGUNCiAgICAgICAgICAgICAgICAgIGltZ19iYWNrZ3JvdW5kID0gcGFscyRzb2phX2IucG5nKSAgIyBwYWxldGEgcGFyYSBmdW5kbw0Kc2V2JHNldmVyaXR5DQoNCmBgYA0KDQoNCiMjIFVzYW5kbyDDrW5kaWNlcyBkZSBpbWFnZW0NCmBgYHtyfQ0KIyDDjW5kaWNlIHBhcmEgc2VnbWVudGFyIGEgZm9saGEgZG8gZnVuZG8sIGRlcG9pcyBhIGRvZW7Dp2EgZGEgZm9saGENCmltYWdlX3NlZ21lbnRfaXRlcihmb2xoYSwgDQogICAgICAgICAgICAgICAgICAgaW5kZXggPSBjKCJCIiwgIk5HUkRJIiksDQogICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpDQoNCiMgSU1QT1JUQU5URTogdGhlc2hvbGQgdmFpIGFsdGVyYXIgYSBzZXZlcmlkYWRlDQpzZXYyIDwtIA0KICBtZWFzdXJlX2Rpc2Vhc2UoZm9saGEsDQogICAgICAgICAgICAgICAgICBpbmRleF9sYiA9ICJCIiwgICAgICAgICAgICAjIMOtbmRpY2UgcGFyYSBzZWdtZW50YXIgYSBmb2xoYSBkbyBmdW5kbw0KICAgICAgICAgICAgICAgICAgaW5kZXhfZGggPSAiTkdSREkiLCAgICAgICAgIyDDrW5kaWNlIHBhcmEgc2VnbWVudGFyIGZvbGhhIGRvZW50ZSBlIHNhZGlhDQogICAgICAgICAgICAgICAgICB0aHJlc2hvbGQgPSBjKCJPdHN1IiwgMCkpICAjIHRocmVzaG9sZCBwYXJhIG9zIGRvaXMgw61uZGljZXMsIHJlc3BlY3RpdmFtZW50ZQ0Kc2V2MiRzZXZlcml0eQ0KDQojIGVtIGxvdGUgKHV0aWxpemFuZG8gYXMgcGFsZXRhcykNCnNldjMgPC0gDQogIG1lYXN1cmVfZGlzZWFzZShwYXR0ZXJuID0gInNveV8iLA0KICAgICAgICAgICAgICAgICAgZGlyX29yaWdpbmFsID0gInNveWJlYW5fcnVzdCIsICAgICMgcGFzdGEgY29tIGFzIGltYWdlbnMgb3JpZ2luYWlzDQogICAgICAgICAgICAgICAgICBkaXJfcHJvY2Vzc2VkID0gInByb2NfcnVzdCIsICAgICAgIyBwYXN0YSBjb20gYXMgaW1hZ2VucyBwcm9jZXNzYWRhcw0KICAgICAgICAgICAgICAgICAgc2F2ZV9pbWFnZSA9IFRSVUUsDQogICAgICAgICAgICAgICAgICBwbG90ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBpbWdfaGVhbHRoeSA9IHBhbHMkc29qYV9oLnBuZywNCiAgICAgICAgICAgICAgICAgIGltZ19zeW1wdG9tcyA9IHBhbHMkc29qYV9zLnBuZywNCiAgICAgICAgICAgICAgICAgIGltZ19iYWNrZ3JvdW5kID0gcGFscyRzb2phX2IucG5nLA0KICAgICAgICAgICAgICAgICAgcGFyYWxsZWwgPSBUUlVFKQ0KIyBzdGFuZGFyZCBhcmVhIGRpYWdyYW1zDQpzYWQoc2V2MywgbiA9IDYpDQoNCnNldjQgPC0gDQogIG1lYXN1cmVfZGlzZWFzZShwYXR0ZXJuID0gInNveV8iLA0KICAgICAgICAgICAgICAgICAgZGlyX29yaWdpbmFsID0gInNveWJlYW5fcnVzdCIsDQogICAgICAgICAgICAgICAgICBwbG90ID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICBpbmRleF9sYiA9ICJCIiwNCiAgICAgICAgICAgICAgICAgIGluZGV4X2RoID0gIk5HUkRJIiwNCiAgICAgICAgICAgICAgICAgIHRocmVzaG9sZCA9IGMoIk90c3UiLCAwKSwNCiAgICAgICAgICAgICAgICAgIHBhcmFsbGVsID0gVFJVRSkNCg0KDQojIHBhbGV0YXMgdnMgw61uZGljZXMgZGUgaW1hZ2VtDQoNCmRmIDwtIA0KICBkYXRhLmZyYW1lKHBhbGV0YXMgPSBzZXYzJHNldmVyaXR5JHN5bXB0b21hdGljLA0KICAgICAgICAgICAgIMOtbmRpY2VzID0gc2V2NCRzZXZlcml0eSRzeW1wdG9tYXRpYykNCmRmDQoNCmdncGxvdChkZiwgYWVzKHBhbGV0YXMsIMOtbmRpY2VzKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gInJlZCIpICsNCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTYpICsNCiAgeGxpbSgwLCAxMDApICsNCiAgeWxpbSgwLCAxMDApICsNCiAgY29vcmRfZXF1YWwoKQ0KDQpgYGANCg0KIyMgRW0gZ3JpZHMNCg0KYGBge3J9DQpmb2xoYV9ncmlkIDwtIGltYWdlX2ltcG9ydCgiZGlzZWFzZV9zaHAuanBnIiwgcGxvdCA9IFRSVUUpDQoNCnNldjUgPC0gDQogIG1lYXN1cmVfZGlzZWFzZV9zaHAoZm9saGFfZ3JpZCwNCiAgICAgICAgICAgICAgICAgICAgICBpbmRleF9sYiA9ICJIVUUyIiwNCiAgICAgICAgICAgICAgICAgICAgICBpbmRleF9kaCA9ICJOR1JESSIsDQogICAgICAgICAgICAgICAgICAgICAgdGhyZXNob2xkID0gYygiT3RzdSIsIDApLA0KICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IDEwLA0KICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLA0KICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAzLA0KICAgICAgICAgICAgICAgICAgICAgIHBsb3QgPSBGQUxTRSkNCnBsb3QoZm9saGFfZ3JpZCkNCnBsb3Qoc2V2NSRzaGFwZWZpbGVzKQ0KcGxvdF9tZWFzdXJlcyhzZXY1LCAic3ltcHRvbWF0aWMiKQ0KDQpgYGANCg0KDQo=